package net.aiion.weave.impl.interception;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import net.aiion.weave.spi.bytecode.Bytecode;
import net.aiion.weave.spi.interception.Interceptable;
import net.aiion.weave.spi.interception.InterceptionContext;
import net.aiion.weave.spi.interception.InterceptionService;
import net.aiion.weave.spi.interception.Interceptor;
import net.aiion.weave.spi.naming.Context;
import net.aiion.weave.spi.naming.Contextual;
import net.aiion.weave.spi.naming.annotations.NotScoped;

public class InterceptionServiceImpl implements Contextual, InterceptionService {
    private Context context;

    private InterceptionServiceImpl() {
    }

    @Override
    public String[] getNames() {
        return new String[] { InterceptionService.class.getName(), InterceptionServiceImpl.class.getName() };
    }

    @Override
    public Class<? extends Annotation> getScope() {
        return NotScoped.class;
    }

    @Override
    public Object getValue() {
        return this;
    }

    @Override
    public void onBound(final Context aContext) {
        context = aContext;
    }

    @Override
    public void onUnbound(final Context aContext) {
        context = null;
    }

    @Override
    public Object interceptInvocation(final Interceptable aInterceptable, final Method aMethod,
        final Object[] aMethodArguments) {
        final InterceptionContext interceptionContext = new InterceptionContextImpl(context, context.lookupAll(Bytecode
            .findClassesByInterfaceClass(Interceptor.class)), aInterceptable, aMethod, aMethodArguments);
        return interceptionContext.forwardInterception();
    }
}
